/*
 * 爱组搭，低代码组件化开发平台
 * ------------------------------------------
 * 受知识产权保护，请勿删除版权申明，开发平台不允许做非法网站，后果自负
 */
package com.aizuda.boot.modules.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.json.JSONUtil;
import com.aizuda.boot.config.properties.FeiShuConfigProperties;
import com.aizuda.boot.modules.auth.domain.entity.ThirdUser;
import com.aizuda.boot.modules.auth.domain.entity.ThirdUserAuth;
import com.aizuda.boot.modules.auth.service.ThirdUserAuthService;
import com.aizuda.boot.modules.auth.service.ThirdUserService;
import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.aizuda.boot.modules.business.contract.dto.UserInfo;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.employee.domain.request.EmployeeQueryById;
import com.aizuda.boot.modules.business.employee.domain.request.EmployeeQueryVO;
import com.aizuda.boot.modules.business.employee.domain.request.EmployeeQueryWithContractVO;
import com.aizuda.boot.modules.business.employee.domain.response.EmployeeQueryShowVO;
import com.aizuda.boot.modules.business.employee.domain.response.EmployeeQueryWithParticipantVO;
import com.aizuda.boot.modules.business.feishu.domain.QueryUserDTO;
import com.aizuda.boot.modules.business.feishu.domain.UserVo;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationInstanceEntity;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationParticipantEntity;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationParticipantMapper;
import com.aizuda.boot.modules.business.negotiation.service.ContractNegotiationService;
import com.aizuda.boot.modules.common.constant.RedisKeyConstant;
import com.aizuda.boot.modules.common.util.RedisService;
import com.aizuda.boot.modules.system.entity.SysDepartment;
import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.boot.modules.system.entity.SysUserDepartment;
import com.aizuda.boot.modules.system.entity.SysUserRole;
import com.aizuda.boot.modules.system.entity.dto.AssignDepartmentsDTO;
import com.aizuda.boot.modules.system.entity.dto.AssignRolesDTO;
import com.aizuda.boot.modules.system.entity.dto.ResetPasswordDTO;
import com.aizuda.boot.modules.system.entity.dto.SysUserDTO;
import com.aizuda.boot.modules.system.entity.vo.*;
import com.aizuda.boot.modules.system.entity.vo.department.DepartmentInfoDTO;
import com.aizuda.boot.modules.system.mapper.SysDepartmentMapper;
import com.aizuda.boot.modules.system.mapper.SysUserMapper;
import com.aizuda.boot.modules.system.service.ISysDepartmentService;
import com.aizuda.boot.modules.system.service.ISysUserDepartmentService;
import com.aizuda.boot.modules.system.service.ISysUserRoleService;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.common.toolkit.RegexUtils;
import com.aizuda.core.api.ApiAssert;
import com.aizuda.service.service.BaseServiceImpl;
import com.aizuda.service.spring.SpringHelper;
import com.aizuda.service.web.UserSession;
import com.baomidou.kisso.SSOHelper;
import com.baomidou.kisso.common.encrypt.MD5;
import com.baomidou.kisso.common.encrypt.MD5Salt;
import com.baomidou.kisso.common.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lark.oapi.Client;
import com.lark.oapi.service.contact.v3.model.FindByDepartmentUserReq;
import com.lark.oapi.service.contact.v3.model.FindByDepartmentUserResp;
import com.lark.oapi.service.contact.v3.model.FindByDepartmentUserRespBody;
import com.lark.oapi.service.contact.v3.model.User;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.config.AuthDefaultSource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 系统用户 服务实现类
 *
 * @author 青苗
 * @since 2021-11-03
 */
@Slf4j
@Service
public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
    @Resource
    private RedisService redisService;

    @Resource
    private ISysUserRoleService sysUserRoleService;
    @Resource
    private ISysUserDepartmentService sysUserDepartmentService;
    @Resource
    @Lazy
    private ContractNegotiationService contractNegotiationService;
    @Resource
    private ContractNegotiationParticipantMapper contractNegotiationParticipantMapper;
    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private ISysDepartmentService sysDepartmentService;
    @Resource
    private SysDepartmentMapper sysDepartmentMapper;
    @Resource
    private FeiShuConfigProperties feiShuConfigProperties;
    @Resource
    private ThirdUserService thirdUserService;
    @Resource
    private ThirdUserAuthService thirdUserAuthService;

    @Override
    public Page<SysUser> page(Page<SysUser> page, SysUserVO vo) {
        Page<SysUser> sysUserPage = new Page<>();
        //超级管理员可看所有数据
        if (AuthUtil.isSuperAdmin()) {
            sysUserPage = baseMapper.selectPageByVO(page, vo, null);
        } else {
            //    非超级管理员可看自己所在系统租户下的数据
            List<SysDepartment> sysDepartmentList = sysDepartmentService.getSysDepartmentListByUserId(AuthUtil.getCurrentUser().getId());
            if (CollectionUtils.isEmpty(sysDepartmentList)) {
                return sysUserPage;
            }
            List<String> sysTenantKeys = sysDepartmentList.stream().map(SysDepartment::getSysTenantKey).distinct().collect(Collectors.toList());
            sysUserPage = baseMapper.selectPageByVO(page, vo, sysTenantKeys);

        }

        if (sysUserPage.getTotal() > 0) {
            // 对外隐藏属性
            this.hiddenData(sysUserPage.getRecords());
            
            // 批量获取用户主部门信息
            List<Long> userIds = sysUserPage.getRecords().stream()
                    .map(SysUser::getId)
                    .collect(Collectors.toList());
            
            try {
                Map<Long, DepartmentInfoDTO> userDepartmentMap = sysDepartmentService.batchGetEmployeeMainDepartments(userIds);
                
                // 为每个用户设置主部门名称
                sysUserPage.getRecords().forEach(user -> {
                    DepartmentInfoDTO deptInfo = userDepartmentMap.get(user.getId());
                    if (deptInfo != null) {
                        user.setDepartmentName(deptInfo.getName());
                    }
                });
            } catch (Exception e) {
                log.error("批量获取用户主部门信息失败，回退到单个查询", e);
                // 如果批量查询失败，回退到原来的单个查询方式
                sysUserPage.getRecords().forEach(user -> {
                    try {
                        DepartmentInfoDTO deptInfo = sysDepartmentService.getEmployeeMainDepartmentForCompatibility(user.getId());
                        if (deptInfo != null) {
                            user.setDepartmentName(deptInfo.getName());
                        }
                    } catch (Exception ex) {
                        log.error("获取用户{}的主部门信息失败", user.getId(), ex);
                    }
                });
            }
        }
        return sysUserPage;
    }

    /**
     * 隐藏数据
     */
    protected List<SysUser> hiddenData(List<SysUser> sysUsers) {
        sysUsers.forEach(t -> {
            t.setPassword(null);
            t.setSalt(null);
        });
        return sysUsers;
    }

    @Override
    public List<SysUser> list20ByUsername(String username) {
        LambdaQueryWrapper<SysUser> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(username)) {
            lqw.like(SysUser::getUsername, username);
            lqw.or().like(SysUser::getRealName, username);
        }
        return this.hiddenData(super.page(Page.of(1, 20, false), lqw).getRecords());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(SysUserDTO dto) {
        ApiAssert.fail(!RegexUtils.matches("(^[A-Za-z]{6,50}$)|(^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,50}$)", dto.getUsername()),
                "用户名，必须是 6 到 50 位 字母 或者 字母数字混合 字符串");
        this.checkPassword(dto.getPassword());
        // 检查登录账号是否存在
        this.checkExists(Wrappers.<SysUser>lambdaQuery().select(SysUser::getId).eq(SysUser::getUsername, dto.getUsername()), "登录账号已存在");
        dto.setSalt(RandomUtil.getCharacterAndNumber(8));
        dto.setPassword(this.encodePassword(dto.getUsername(), dto.getSalt(), dto.getPassword()));
        ApiAssert.fail(!super.save(dto), "用户信息保存失败");
        if (CollectionUtils.isNotEmpty(dto.getRoleIds())) {
            ApiAssert.fail(!this.assignRoles(dto), "角色分配保存失败");
        }
        if (CollectionUtils.isNotEmpty(dto.getDepartmentIds())) {
            ApiAssert.fail(!this.assignDepartments(dto), "部门分配保存失败");
        }
        return true;
    }

    protected void checkPassword(String password) {
        ApiAssert.fail(!RegexUtils.isPassword(password), "登录密码必须为6-20位大小写字母数字特殊字符组合不包含@符合");
    }

    protected String encodePassword(String username, String salt, String password) {
        return MD5Salt.encode(username + salt, MD5.toMD5(password));
    }

    protected boolean assignRoles(SysUserDTO dto) {
        // 分配角色
        AssignRolesDTO ard = new AssignRolesDTO();
        ard.setRoleIds(dto.getRoleIds());
        ard.setUserIds(Collections.singletonList(dto.getId()));
        return sysUserRoleService.assignRoles(ard);
    }

    protected boolean assignDepartments(SysUserDTO sud) {
        // 分配部门
        AssignDepartmentsDTO dto = new AssignDepartmentsDTO();
        dto.setDepartmentIds(sud.getDepartmentIds());
        dto.setUserIds(Collections.singletonList(sud.getId()));
        return sysUserDepartmentService.assignDepartments(dto, sud.getMainDeptId());
    }

    @Override
    public boolean updateById(SysUserDTO dto) {
        ApiAssert.fail(!super.updateById(dto), "用户信息保存失败");
        // 登录账号，密码，盐不允许更新
        dto.setUsername(null);
        dto.setPassword(null);
        dto.setSalt(null);
        ApiAssert.fail(!this.assignRoles(dto), "角色分配保存失败");
        ApiAssert.fail(!this.assignDepartments(dto), "部门分配保存失败");
        return true;
    }

    @Override
    public boolean updateStatusById(Long id, Integer status) {
        SysUser sysUser = new SysUser();
        sysUser.setId(id);
        sysUser.setStatus(Objects.equals(status, 1) ? 1 : 0);
        return super.updateById(sysUser);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean resetPassword(ResetPasswordDTO dto) {
        this.checkPassword(dto.getPassword());
        List<Long> ids = dto.getIds();
        for (Long id : ids) {
            SysUser sysUser = super.getOne(Wrappers.<SysUser>lambdaQuery()
                    .select(SysUser::getUsername, SysUser::getSalt)
                    .eq(SysUser::getId, id));
            if (null == sysUser) {
                continue;
            }
            SysUser temp = new SysUser();
            temp.setId(id);
            temp.setPassword(this.encodePassword(sysUser.getUsername(), sysUser.getSalt(), dto.getPassword()));
            super.updateById(temp);
        }
        return true;
    }

    @Override
    public SysUser getById(Long id) {
        if (null == id) {
            // 未指定ID读取当前登录用户信息
            id = UserSession.getLoginInfo().getId();
        }
        SysUser sysUser = baseMapper.selectById(id);
        if (null != sysUser) {
            // 隐藏敏感数据
            sysUser.setSalt(null);
            sysUser.setPassword(null);
        }
        return sysUser;
    }

    @Override
    public SysUserRelIdsVO getRelIdsById(Long id) {
        SysUserRelIdsVO vo = new SysUserRelIdsVO();
        vo.setRoleIds(sysUserRoleService.listRoleIdsByUserId(id));
        vo.setDepartmentIds(sysUserDepartmentService.listDepartmentIdsByUserId(id));
        vo.setMainDeptId(sysUserDepartmentService.getMainDepartmentIdByUserId(id));
        return vo;
    }


    @Override
    public List<EmployeeQueryShowVO> queryEmployee(EmployeeQueryVO query) {
        if (null == query || null == query.getMsg()) {
            return new ArrayList<>();
        }
        List<EmployeeQueryShowVO> rawEmployees = sysUserMapper.queryEmployee(query.getMsg());
        // 进行去重处理
        return deduplicateEmployees(rawEmployees);
    }

    @Override
    public List<EmployeeQueryShowVO> queryEmployeeShow(EmployeeQueryById employeeIds) {
        // 参数验证
        if (org.springframework.util.CollectionUtils.isEmpty(employeeIds.getEmployeeIds())) {
            log.warn("员工ID列表为空，返回空结果");
            return new ArrayList<>();
        }

        // 获取当前用户信息（用于日志记录）
        UserInfo currentUser = AuthUtil.getCurrentUser();
        if (Objects.isNull(currentUser)) {
            log.warn("当前用户未登录，不允许查询员工信息");
        }

        try {
            // 调用service层方法查询员工
            List<EmployeeQueryShowVO> employeeList = sysUserMapper.queryEmployeeShow(employeeIds.getEmployeeIds());

            if (org.springframework.util.CollectionUtils.isEmpty(employeeList)) {
                log.info("根据员工ID列表未找到符合条件的员工信息，员工ID列表：{}", employeeIds);
                return new ArrayList<>();
            }

            log.info("根据员工ID列表成功查询到{}名员工，输入ID数量：{}", employeeList.size(), employeeIds.getEmployeeIds().size());
            return employeeList;
        } catch (Exception e) {
            log.error("根据员工ID列表查询员工信息时发生异常，员工ID列表：{}", employeeIds, e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<EmployeeQueryWithParticipantVO> queryEmployeeWithNegotiationStatus(EmployeeQueryWithContractVO query) {
        try {
            // 参数验证
            if (query == null || query.getContractId() == null) {
                log.warn("查询参数无效，contractId不能为空");
                return new ArrayList<>();
            }

            // 1. 获取当前查询人的主部门所在的租户
            UserInfo currentUser = AuthUtil.getCurrentUser();
            if (currentUser == null) {
                log.warn("无法获取当前用户信息");
                return new ArrayList<>();
            }

            Long currentUserId = currentUser.getId();
            SysDepartment mainDepartment = sysDepartmentMapper.selectMainDepartmentByUserId(currentUserId);
            if (mainDepartment == null) {
                log.warn("当前用户 {} 没有主部门", currentUserId);
                return new ArrayList<>();
            }

            String tenantKey = mainDepartment.getSysTenantKey();
            if (tenantKey == null || tenantKey.trim().isEmpty()) {
                log.warn("当前用户主部门 {} 没有租户信息", mainDepartment.getName());
                return new ArrayList<>();
            }

            log.info("当前用户 {} 的主部门: {} (ID: {}), 租户: {}", currentUserId, mainDepartment.getName(), mainDepartment.getId(), tenantKey);

            // 2. 查询当前租户下的员工列表
            List<EmployeeQueryShowVO> employees = new ArrayList<>();
            if (query.getMsg() != null && !query.getMsg().trim().isEmpty()) {
                // 查询租户下符合条件的员工
                List<EmployeeQueryShowVO> rawEmployees = queryEmployeeByTenantAndKeyword(tenantKey, query.getMsg());

                // 去重处理：一个员工可能关联多个部门，需要去重并选择主部门
                employees = deduplicateEmployees(rawEmployees);
                log.info("在租户 {} 下找到 {} 个符合条件的员工", tenantKey, employees.size());
            } else {
                log.info("查询条件为空，返回空列表");
                return new ArrayList<>();
            }

            if (employees.isEmpty()) {
                log.info("未找到匹配的员工，返回空列表");
                return new ArrayList<>();
            }

            // 2. 根据contractId查找协商实例
            ContractNegotiationInstanceEntity instance = null;
            try {
                instance = contractNegotiationService.getNegotiationByContractIdAllStatus(query.getContractId().intValue());
            } catch (Exception e) {
                log.warn("根据contractId {}查找协商实例失败，可能该合同没有协商实例", query.getContractId(), e);
            }

            // 3. 如果有协商实例，查询参与者列表
            Map<Long, ContractNegotiationParticipantEntity> participantMap = new HashMap<>();
            if (instance != null) {
                try {
                    LambdaQueryWrapper<ContractNegotiationParticipantEntity> participantWrapper = new LambdaQueryWrapper<>();
                    participantWrapper.eq(ContractNegotiationParticipantEntity::getInstanceId, instance.getId());
                    List<ContractNegotiationParticipantEntity> participants = contractNegotiationParticipantMapper.selectList(participantWrapper);

                    // 转换为Map便于快速查找
                    participantMap = participants.stream()
                            .collect(Collectors.toMap(
                                    ContractNegotiationParticipantEntity::getEmployeeId,
                                    participant -> participant,
                                    (existing, replacement) -> existing
                            ));

                    log.info("找到协商实例ID: {}, 参与者数量: {}", instance.getId(), participants.size());
                } catch (Exception e) {
                    log.error("查询协商参与者失败，实例ID: {}", instance.getId(), e);
                }
            }

            // 4. 转换结果并标记参与者状态
            List<EmployeeQueryWithParticipantVO> results = new ArrayList<>();
            for (EmployeeQueryShowVO employee : employees) {
                EmployeeQueryWithParticipantVO result = new EmployeeQueryWithParticipantVO();

                // 复制基本属性
                BeanUtil.copyProperties(employee, result);

                // 检查是否为协商参与者
                ContractNegotiationParticipantEntity participant = participantMap.get(employee.getId());
                if (participant != null) {
                    result.setIsNegotiationParticipant(true);
                    result.setParticipantType(participant.getParticipantType());
                    result.setIsViewed(participant.getIsViewed());
                    result.setIsConfirmed(participant.getIsConfirmed());
                } else {
                    result.setIsNegotiationParticipant(false);
                    result.setParticipantType(null);
                    result.setIsViewed(null);
                    result.setIsConfirmed(null);
                }

                results.add(result);
            }

            log.info("成功查询员工{}人，其中协商参与者{}人", results.size(), participantMap.size());
            return results;

        } catch (Exception e) {
            log.error("查询员工协商状态失败", e);
            return new ArrayList<>();
        }
    }

    /**
     * 根据租户和关键词查询员工
     *
     * @param tenantKey 租户键
     * @param keyword 关键词（姓名、工号等）
     * @return 员工列表
     */
    private List<EmployeeQueryShowVO> queryEmployeeByTenantAndKeyword(String tenantKey, String keyword) {
        try {
            log.info("查询租户 {} 下关键词为 '{}' 的员工", tenantKey, keyword);

            // 使用 baseMapper 查询指定租户下符合条件的员工
            List<EmployeeQueryShowVO> employees = baseMapper.selectEmployeeByTenantAndKeyword(tenantKey, keyword);

            log.info("在租户 {} 下找到 {} 个符合条件的员工", tenantKey, employees.size());
            return employees;

        } catch (Exception e) {
            log.error("查询租户员工失败，tenantKey: {}, keyword: {}", tenantKey, keyword, e);
            return new ArrayList<>();
        }
    }

    /**
     * 员工去重处理
     * 一个员工可能关联多个部门，选择主部门作为显示部门
     *
     * @param rawEmployees 原始员工列表（可能包含重复员工）
     * @return 去重后的员工列表
     */
    private List<EmployeeQueryShowVO> deduplicateEmployees(List<EmployeeQueryShowVO> rawEmployees) {
        if (rawEmployees == null || rawEmployees.isEmpty()) {
            return new ArrayList<>();
        }

        // 使用LinkedHashMap保持插入顺序，key为员工ID，value为员工信息
        Map<Long, EmployeeQueryShowVO> employeeMap = new LinkedHashMap<>();

        for (EmployeeQueryShowVO employee : rawEmployees) {
            if (employee.getId() != null) {
                if (!employeeMap.containsKey(employee.getId())) {
                    // 第一次遇到该员工，先添加
                    employeeMap.put(employee.getId(), employee);
                } else {
                    // 员工已存在，需要判断是否需要更新为主部门信息
                    EmployeeQueryShowVO existingEmployee = employeeMap.get(employee.getId());

                    // 获取员工的主部门信息
                    try {
                        SysDepartment mainDepartment = sysDepartmentMapper.selectMainDepartmentByUserId(employee.getId());
                        if (mainDepartment != null) {
                            // 如果当前员工的部门是主部门，则更新
                            if (employee.getDeptId() != null && employee.getDeptId().equals(mainDepartment.getId())) {
                                employee.setDeptName(mainDepartment.getName());
                                employeeMap.put(employee.getId(), employee);
                                log.debug("更新员工{}的主部门信息: {}", employee.getId(), mainDepartment.getName());
                            }
                        }
                    } catch (Exception e) {
                        log.warn("获取员工{}主部门信息失败，保持原有部门信息", employee.getId(), e);
                    }
                }
            }
        }

        // 对于没有找到主部门的员工，再次尝试设置主部门信息
        for (EmployeeQueryShowVO employee : employeeMap.values()) {
            try {
                SysDepartment mainDepartment = sysDepartmentMapper.selectMainDepartmentByUserId(employee.getId());
                if (mainDepartment != null &&
                        (employee.getDeptId() == null || !employee.getDeptId().equals(mainDepartment.getId()))) {
                    // 更新为主部门信息
                    employee.setDeptId(mainDepartment.getId());
                    employee.setDeptName(mainDepartment.getName());
                    log.debug("设置员工{}的主部门信息: {}", employee.getId(), mainDepartment.getName());
                }
            } catch (Exception e) {
                log.warn("获取员工{}主部门信息失败", employee.getId(), e);
            }
        }

        List<EmployeeQueryShowVO> result = new ArrayList<>(employeeMap.values());
        log.info("员工去重处理：原始数量{}, 去重后数量{}", rawEmployees.size(), result.size());

        return result;
    }

    /**
     * 根据部门ID查询员工信息
     *
     * @param departmentId
     * @return
     */
    @Override
    public List<Long> getEmployeeIdsByMainDepartment(Long departmentId) {
        return sysUserMapper.getEmployeeIdsByMainDepartment(departmentId);
    }

    @Override
    public void syncFeiShuUser() {
        //    1.获取系统中所有飞书关联部门
        Map<String, FeiShuConfigProperties.FeiShuAppConfig> apps = feiShuConfigProperties.getApps();
        if (apps.isEmpty()) {
            log.warn("未配置飞书应用，无法同步用户信息");
            return;
        }
        //一个机构一个机构同步
        log.info("开始同步飞书用户信息...");
        apps.values().forEach(appConfig -> {
            // 获取飞书部门列表
            sysDepartmentService.lambdaQuery()
                    .eq(SysDepartment::getTenantKey, appConfig.getTenantKey())
                    .list()
                    .forEach(department -> {
                        log.info("开始同步企业{}->{}下用户", appConfig.getName(), department.getName());
                        syncFeiShuUserByDepartment(department, appConfig, null);
                        log.info("同步企业{}->{}下用户完成", appConfig.getName(), department.getName());
                    });

            log.info("同步企业{}下所有部门用户信息完成", appConfig.getName());

        });

        //    2.同步完成后，根据手机号合并用户
        log.info("开始合并手机号相同的用户...");
        mergeUser();
        log.info("合并手机号相同的用户完成");


    }

    @Override
    public LoginUserVo getUserInfo() {

        Long userId = UserSession.getLoginInfo().getId();

        //先从缓存中获取
        LoginUserVo cacheLoginUserVo = (LoginUserVo) redisService.getCacheObject(RedisKeyConstant.LOGIN_USER_PREFIX + userId);
        if (cacheLoginUserVo != null) {
            return cacheLoginUserVo;
        }

//构建返回值
        LoginUserVo loginUserVo = new LoginUserVo();
        SysUser sysUser = getById(null);// 获取当前登录用户信息;

        BeanUtil.copyProperties(sysUser, loginUserVo);
        //获取当前用户存在的所有系统租户信息
        // 查询员工所属的所有部门(接入飞书后,必须存在部门信息) - 优先主部门
        List<SysUserDepartment> userDepartments = sysUserDepartmentService.lambdaQuery()
                .eq(SysUserDepartment::getUserId, sysUser.getId())
                .orderByDesc(SysUserDepartment::getIsMain)  // 主部门优先
                .orderByAsc(SysUserDepartment::getId)       // 其次按ID排序
                .list();

        if (CollectionUtil.isEmpty(userDepartments)) {
            redisService.setCacheObject(RedisKeyConstant.LOGIN_USER_PREFIX + sysUser.getId(), loginUserVo, 30, TimeUnit.MINUTES);
            return loginUserVo;
        }

        List<Long> depIdList = userDepartments.stream()
                .map(SysUserDepartment::getDepartmentId)
                .toList();

        List<TenantVo> tenantVoList = new ArrayList<>(depIdList.size());
        Set<Object> seen = new HashSet<>();
        List<SysDepartment> departments = sysDepartmentService.lambdaQuery()
                .in(SysDepartment::getId, depIdList)
                .eq(SysDepartment::getStatus, 1)
                .list();

        // 创建部门ID到部门对象的映射
        Map<Long, SysDepartment> deptMap = departments.stream()
                .collect(Collectors.toMap(SysDepartment::getId, d -> d));

        // 按照用户部门的顺序（主部门优先）处理部门信息
        for (SysUserDepartment userDept : userDepartments) {
            SysDepartment department = deptMap.get(userDept.getDepartmentId());
            if (department == null || !seen.add(department.getSysTenantKey())) {
                continue;
            }

            // 设置主部门详细信息和部门名称（只要是主部门就设置，不管租户）
            if (userDept.getIsMain() != null && userDept.getIsMain() == 1) {
                loginUserVo.setMainDeptInfo(department);
                loginUserVo.setDepartmentName(department.getName());
            }

            //获取飞书部门

            //如果部门标识独立租户则租户名称为部门名称否则获取顶级部门名称
            SysDepartment sysTenantDept = sysDepartmentService.getSysTenantDept(UserSession.getLoginInfo().getId(), department.getId());
            tenantVoList.add(TenantVo.builder()
                    .tenantKey(sysTenantDept.getSysTenantKey())
                    .tenantName(sysTenantDept.getName())
                    .build());
        }

        // 如果没有主部门，设置第一个部门作为主部门信息（备选方案）
        if (loginUserVo.getMainDeptInfo() == null && !userDepartments.isEmpty()) {
            SysDepartment firstDept = deptMap.get(userDepartments.get(0).getDepartmentId());
            if (firstDept != null) {
                loginUserVo.setMainDeptInfo(firstDept);
            }
        }

        //获取当前用户的系统租户信息
        TenantVo tenantVo = tenantVoList.stream()
                .filter(t -> Objects.equals(t.getTenantKey(), SSOHelper.getSSOToken(SpringHelper.getCurrentRequest()).getTenantId()))
                .findFirst()
                .orElse(null);

        loginUserVo.setSysTenantVo(tenantVo);

        // 设置 sysTenantKey 字段以确保兼容性
        if (tenantVo != null) {
            loginUserVo.setSysTenantKey(tenantVo.getTenantKey());
        }

        loginUserVo.setSysTenantList(tenantVoList);
        //获取当前部门信息
        redisService.setCacheObject(RedisKeyConstant.LOGIN_USER_PREFIX + sysUser.getId(), loginUserVo, 30, TimeUnit.MINUTES);

        return loginUserVo;
    }

    @Override
    public boolean clearUserCache(Long userId) {
        try {
            // 如果没有指定userId，则清除当前登录用户的缓存
            if (userId == null) {
                userId = UserSession.getLoginInfo().getId();
            }

            // 删除用户信息缓存
            redisService.deleteObject(RedisKeyConstant.LOGIN_USER_PREFIX + userId);

            log.info("成功清除用户缓存，用户ID: {}", userId);
            return true;
        } catch (Exception e) {
            log.error("清除用户缓存失败，用户ID: {}", userId, e);
            return false;
        }
    }

    @Override
    public SingleResponse<List<UserVo>> getAtUsers(QueryUserDTO queryUserDTO) {
        UserInfo currentUser = AuthUtil.getCurrentUser();
        String sysTenantKey = currentUser.getSysTenantKey();
        List<UserVo> userList = sysUserMapper.getAtUsers(sysTenantKey, queryUserDTO.getKeyword());
        return SingleResponse.of(userList);
    }

    @Override
    public String getDepartmentNameById(Long departmentId) {
        if (departmentId == null) {
            return null;
        }

        try {
            com.aizuda.boot.modules.system.entity.SysDepartment department = sysDepartmentService.getById(departmentId);
            return department != null ? department.getName() : null;
        } catch (Exception e) {
            log.error("获取部门名称失败，部门ID：{}", departmentId, e);
            return null;
        }
    }

    private void syncFeiShuUserByDepartment(SysDepartment department, FeiShuConfigProperties.FeiShuAppConfig appConfig, String pageToken) {
        Client client = Client.newBuilder(appConfig.getAppId(), appConfig.getAppSecret()).logReqAtDebug(true).build();

        try {

            FindByDepartmentUserResp resp = client.contact().user().findByDepartment(
                    FindByDepartmentUserReq.newBuilder()
                            .departmentId(department.getOpenDepartmentId())
                            .pageSize(50)
                            .pageToken(pageToken)
                            .build()
            );

            if (resp.getCode() != 0) {
                log.error("同步部门失败,飞书接口报错，错误码: {}, 错误信息: {}", resp.getCode(), resp.getMsg());
                log.error("详细错误信息:{}", resp.getError());
                return;
            }

            FindByDepartmentUserRespBody data = resp.getData();
            if (data == null || data.getItems() == null || data.getItems().length == 0) {
                log.info("部门：{} 下无用户信息需要同步", department.getName());
                return;
            }
            //删除当前部门下的非主部门用户关联关系，保留主部门记录（is_main=1）
            sysUserDepartmentService.remove(Wrappers.<SysUserDepartment>lambdaQuery()
                    .eq(SysUserDepartment::getDepartmentId, department.getId())
                    .and(wrapper -> wrapper.ne(SysUserDepartment::getIsMain, 1)
                            .or().isNull(SysUserDepartment::getIsMain)));
            List<ThirdUser> existList = thirdUserService.lambdaQuery()
                    .eq(ThirdUser::getSource, AuthDefaultSource.FEISHU.getName())
                    .in(ThirdUser::getUuid, Arrays.stream(data.getItems()).map(User::getUnionId).toList())
                    .list();
            //ToDo  先简单粗暴处理 后续待优化
            for (User item : data.getItems()) {
                //    根据用户飞书唯一id获取 third_user 表中数据 如果没查到 则说明 用户属于第一次同步
                //    如果查到,则筛选当前企业主体下是否存在该用户
                existList.stream()
                        .filter(t -> Objects.equals(t.getUuid(), item.getUnionId()))
                        .findFirst()
                        .ifPresentOrElse(thirdUser -> {
                            // 如果查到 则说明是第一次同步
                            log.info("飞书用户{}已存在，跳过创建", item.getName());
                            ThirdUserAuth thirdUserAuth = thirdUserAuthService.lambdaQuery()
                                    .eq(ThirdUserAuth::getThirdUserId, thirdUser.getId())
                                    .one();
                            //   存在直接跳过
                            log.info("更新{}部门关系", item.getName());
                            //    检查是否已存在该用户与部门的关系记录
                            SysUserDepartment existingRelation = sysUserDepartmentService.getOne(
                                    Wrappers.<SysUserDepartment>lambdaQuery()
                                            .eq(SysUserDepartment::getUserId, thirdUserAuth.getUserId())
                                            .eq(SysUserDepartment::getDepartmentId, department.getId())
                            );

                            // 如果不存在关系记录，则创建新记录
                            if (existingRelation == null) {
                                sysUserDepartmentService.save(SysUserDepartment.builder()
                                        .userId(thirdUserAuth.getUserId())
                                        .departmentId(department.getId())
                                        .isMain(0)  // 同步的部门默认不是主部门，保留用户手动设置的主部门
                                        .build());
                                log.info("为用户{}创建新的部门关系", item.getName());
                            } else {
                                log.info("用户{}与部门{}的关系已存在，跳过创建", item.getName(), department.getName());
                            }
                        }, () -> {
                            // 如果没查到 则说明是第一次同步
                            log.info("飞书用户{}不存在，开始创建", item.getName());
                            SysUser sysUser = new SysUser();
                            sysUser.setUsername(PinyinUtil.getPinyin(item.getName(), "") + "_" + RandomUtil.getCharacterAndNumber(4));
                            sysUser.setNickName(item.getName());
                            sysUser.setAvatar(item.getAvatar().getAvatarOrigin());
                            sysUser.setRealName(item.getName());
                            sysUser.setEmail(item.getEmail());
                            sysUser.setPhone(item.getMobile());
                            sysUser.setStatus(1);
                            super.save(sysUser);

                            // 保存第三方用户信息
                            ThirdUser thirdUser = new ThirdUser();
                            thirdUser.setUuid(item.getUnionId());
                            thirdUser.setSource(AuthDefaultSource.FEISHU.getName());
                            thirdUser.setOpenId(item.getOpenId());
                            thirdUser.setTenantKey(department.getTenantKey());
                            thirdUser.setUserId(item.getUserId());
                            thirdUserService.save(thirdUser);

                            // 保存第三方授权信息
                            thirdUserAuthService.save(ThirdUserAuth.builder()
                                    .thirdUserId(thirdUser.getId())
                                    .userId(sysUser.getId())
                                    .userId(sysUser.getId())
                                    .build());

                            //    保存部门关联关系 - 新用户的第一个部门设为主部门
                            sysUserDepartmentService.save(SysUserDepartment.builder()
                                    .userId(sysUser.getId())
                                    .departmentId(department.getId())
                                    .isMain(1)  // 新用户的第一个部门默认为主部门
                                    .build());
                            log.info("飞书用户信息创建成功: {}", JSONUtil.toJsonStr(sysUser));
                        });

            }

            if (data.getHasMore()) {
                // 如果还有更多数据，递归调用
                syncFeiShuUserByDepartment(department, appConfig, data.getPageToken());
            } else {
                log.info("部门：{} 下用户信息同步完成", department.getName());
            }


        } catch (Exception e) {
            log.error("同步飞书用户信息失败，部门：{}，错误信息：{}", department.getName(), e.getMessage(), e);
            return;
        }

    }


    /**
     * 合并手机号相同的用户
     * 1.查询所有手机号相同的用户
     * 2.根据手机号分组
     * 3.遍历分组，合并用户
     */
    protected void mergeUser() {
        // 1.查询所有手机号相同的用户

        List<SysUser> repeatUserList = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery()
                .select(SysUser::getPhone)
                .isNotNull(SysUser::getPhone)
                .ne(SysUser::getPhone, "")
                .groupBy(SysUser::getPhone)
                .having("count(id) > 1"));

        if (CollectionUtils.isEmpty(repeatUserList)) {
            log.info("没有需要合并的用户");
            return;

        }
        List<SysUser> sysUsers = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery()
                .in(SysUser::getPhone, repeatUserList.stream()
                        .map(SysUser::getPhone)
                        .collect(Collectors.toSet()))
        );

        // 2.根据手机号分组
        sysUsers.stream()
                .collect(Collectors.groupingBy(SysUser::getPhone))
                .forEach((phone, users) -> {
                    if (users.size() <= 1) {
                        return; // 如果分组内只有一个用户，跳过
                    }
                    log.info("合并手机号为 {} 的用户,数量: {}", phone, users.size());
                    // 3.遍历分组，合并用户
                    mergeUsers(users);
                });

    }

    /**
     * 合并用户
     * 选择第一个用户作为主用户，其他用户的角色和部门都转移到主用户上，然后删除其他用户
     *
     * @param users 待合并的用户列表
     */
    private void mergeUsers(List<SysUser> users) {
        // 选择第一个用户作为主用户
        SysUser mainUser = users.get(0);
        List<Long> mergedUserIds = new ArrayList<>();

        for (int i = 1; i < users.size(); i++) {
            SysUser userToMerge = users.get(i);
            mergedUserIds.add(userToMerge.getId());

            // 合并角色
            sysUserRoleService.lambdaUpdate()
                    .set(SysUserRole::getUserId, mainUser.getId())
                    .eq(SysUserRole::getUserId, userToMerge.getId())
                    .update();

            // 合并部门
            sysUserDepartmentService.lambdaUpdate()
                    .set(SysUserDepartment::getUserId, mainUser.getId())
                    .set(SysUserDepartment::getIsMain, 0)
                    .eq(SysUserDepartment::getUserId, userToMerge.getId())
                    .update();

            // 合并第三方用户信息
            thirdUserAuthService.lambdaUpdate()
                    .set(ThirdUserAuth::getUserId, mainUser.getId())
                    .eq(ThirdUserAuth::getUserId, userToMerge.getId())
                    .update();

            // 删除被合并的用户
            super.removeById(userToMerge.getId());
        }

        log.info("合并完成，主用户ID: {}, 被合并的用户ID: {}", mainUser.getId(), mergedUserIds);
    }

    @Override
    public List<UserAvatarVO> getUserAvatarsByIds(List<Long> userIds) {
        // 参数验证
        if (CollectionUtils.isEmpty(userIds)) {
            log.warn("用户ID列表为空，返回空结果");
            return new ArrayList<>();
        }

        try {
            // 调用mapper方法查询用户头像信息
            List<UserAvatarVO> avatarList = sysUserMapper.getUserAvatarsByIds(userIds);

            if (CollectionUtils.isEmpty(avatarList)) {
                log.info("根据用户ID列表未找到符合条件的用户头像信息，用户ID列表：{}", userIds);
                return new ArrayList<>();
            }

            log.info("根据用户ID列表成功查询到{}个用户头像，输入ID数量：{}", avatarList.size(), userIds.size());
            return avatarList;
        } catch (Exception e) {
            log.error("根据用户ID列表查询用户头像信息时发生异常，用户ID列表：{}", userIds, e);
            return new ArrayList<>();
        }
    }
}
